# 列表
# 有序的、可变的（可以增删改）、里面的元素类型可以不唯一、查找速度会随着长度的增加而变慢

# 定义：[元素1,元素2,元素3,元素4......]
list1 = [1, 2, 3, 4, 5, 3, 6, 7, 8, 9, 'a', 'b', 11.1, True]
print(list1, type(list1))

# append()：往list的末尾增加一个元素
list1.append(12)
print(list1)

# remove()：指定一个value进行移除，只移除第一次出现的与指定的value相等的元素
# 如果指定的value在list中没有出现过一次，那么会直接抛出ValueError异常
print(list1.remove(3))
# list1.remove(30) # 30 没有在list中，所以会抛出异常
print(list1)

# pop()：指定一个index，移除并返回索引位置对应的元素，如果未传入索引则默认移除并返回最后一个元素
print(list1.pop())
print(list1)
list1.pop(-4)
print(list1)

# del ：通过索引取出元素并进行删除
del list1[9]
print(list1)

# index(a,b,c)：可以传入3个参数
# a：需要查找的值
# b：查找的起始范围 默认是0
# c：查找范围的结束位置 默认是最后一个元素
# 如果找到即返回元素对应的索引，未找到直接抛出ValueError异常
print(list1.index(3))
list1.pop(list1.index(3))
print(list1)

# insert(a,b)：需要指定两个参数
# a：需要插入的位置
# b：需要插入的值
list1.insert(2, 3)
print(list1)

# copy()：将当前list中的所有元素复制一份 并重新构造一个list返回
# 后续再对list修改不会影响copy出来的新list
list1Copy = list1.copy()
print(list1Copy, type(list1Copy))
list1.pop()
print(list1)
print(list1Copy)

list1.append(3)
list1.append(3)
list1.append(3)
# count()：指定一个value，统计list中该value出现了几次
print(list1.count(3))

# extend()：传入一个可以遍历的容器，一般是list，然后将其合并
list1.extend([1, 2, 3, 4])
print(list1)

# 实际上extend方法同 + 类似，都是扩充元素
# 但是extend会在原来的list上进行修改，+ 不会修改原来的list
print(list1 + [4, 5, 6, 7])
print(list1)

# sort()：对list中的元素进行排序，默认升序
# 如果想降序，可以指定参数reverse=True
list1.sort()  # 升序
print(list1)
list1.sort(reverse=True)  # 降序
print(list1)

# reverse()：将list倒转
list1.reverse()

print(list1)

# 切片
# list1[起始位置:结束位置:步长]
# 起始位置和结束位置都是索引
# [起始位置,结束位置) 左闭右开（包含起始位置，不包含结束位置）
# 步长：几个元素取一次
print(list1[4:9:1])

print(list1[::3])

print(list1[-13:-8])

# 步长还可以指定为负数：表示从右往左取
print(list1[4:1:-1])

# 使用切片的方式将list倒转
print(list1[::-1])

# 清空所有的元素
list1.clear()
print(list1)

# 嵌套列表：列表中包含列表
list2 = [1, 2, 3]
list3 = [list2, 'a', 'b', 'c']
print(list3)
list3[0][1] = 22
print(list3[0][1])

print("*" * 30)
# 元组
# 定义：(元素1,元素2,元素3,元素4......)
# 有序，元素的类型可以不唯一，不可变（元组一旦初始化完成就不能修改）
tuple1 = (1, 1, 1, 1, 2, 3, 4, 5, 'a', 'bc', False, 1.11)
print(tuple1, type(tuple1))
print(tuple1[0])
# tuple1[0] = 11 # 元组不可以修改，会抛出TypeError异常

# count()：同list中的count，传入一个value，统计value出现的次数
# 注意：True会被当作1，False会被当作0
print(tuple1.count(0))

# index()：同list中的index
print(tuple1.index(2))

# 注意一：当元组只有一个元素的时候，在进行初始化时记得加上"逗号"
tuple2 = ('a')
print(tuple2, type(tuple2))  # a <class 'str'>

tuple2 = ('a',)
print(tuple2, type(tuple2))  # ('a',) <class 'tuple'>

# 注意二：元组"不可变":实际上不可变指的是 tuple中元素的指向不变
list4 = [1, 2, 3]
tuple3 = ('a', 'b', 1, list4)
print(tuple3, type(tuple3))
tuple3[3][1] = 22
print(tuple3, type(tuple3))

# dict字典
# 定义：{"key":"value","k1":"v1","k3":"v3","k4":"v4",......}
# 每个元素都是k:v键值对，元素之间用 逗号 分隔，k:v直接用 冒号 分隔
# 适用于快速查找的场景，查找速度并不会随着元素的增加而变慢
# 可变的，无序的

dict1 = {"k1": "v1", "k2": "v2", "k3": "v3"}
print(dict1, type(dict1))
print(dict1["k3"])
dict1["k3"] = 'vv3'
print(dict1)
# dict1[0] # 抛出异常 因为 0 不是 dict1中的key 字典是无序的，不能通过index去取元素，只能通过key去取

# pop()根据传入的key返回对应的value，并将k:v移除
print(dict1.pop("k2"))
print(dict1)

dict2 = dict1.copy()
print(dict2, type(dict2))

# items() 返回一个dict_items结构
# 实际上是一个list，list中每个元素都是元组，每个元组对应一对k:v
# 该方法通常适用于遍历dict
print(dict1.items(), type(dict1.items()))
for item in dict1.items():
    print(item)

for key, value in dict1.items():
    print(key, value)

# values() 以list（dict_values）的形式返回字典的所有的value
print(dict1.values())

# keys() 以list（dict_keys）的形式返回字典的所有的value
print(dict1.keys())

# 根据传入的k的集合（list） 创建一个value都为None的新的字典
dict3 = dict1.fromkeys(["k1", "kk1", "kk2"])
print(dict3)

# get() 根据传入的key 返回对应的value
# 推荐使用这种方式 根据key获取value
# 当key不存在的时候不会报错，而且可以指定默认值
# dict1["k4"]
print(dict1.get("k4", "指定一个值"))

dict1.popitem()
print(dict1)

# 当不知道插入的key是否存在，又不想在key已经存在时 将value替换掉
# 就可以使用setdefault进行安全的插入
print(dict1.setdefault("k5", "vvvv1"))
print(dict1)
dict1['k6'] = 'v6'
print(dict1)

dict2 = {"k1": "vv1", "k2": "v2", "k5": "vv5", "k7": "v7"}

# update() 传入一个字典，根据字典的key:value 更新原有的key:value键值对
dict1.update(dict2)
print(dict1)

# 注意：字典的key必须是不可变的，key不能重复，如果在构造字典的时候，存在相同的key，后面的k:v键值对会覆盖前面的
# 字典的value不做要求
# 不可变的：五大基本数据类型、tuple
list5 = [1, 2, 3]
# dict3 = {list5: "v"} # TypeError: unhashable type: 'list'
tuple4 = (1, 2, 3)
dict3 = {tuple4: 'v'}
# dict4 = {dict3: "v"} # TypeError: unhashable type: 'dict'
dict5 = {1: '1', 1: '2', 1.1: '1.1', "key": 'vvv', True: 'True', False: 'False', None: 'none'}
print(dict5)
print(dict5.get(1))

dict1.clear()
print(dict1)

# set集合
# 定义：{元素1,元素2,元素3,元素4......}
# 集合中的元素会自动去重，元素类型可以不唯一
# 无序的，可变的

set1 = {1, 2, 3, 4, 5, 1, 1, 1, 'a', 'a', 'b', 'c', 1.1}
print(set1, type(set1))
# set1[0] # TypeError: 'set' object is not subscriptable
set1.add(10)
print(set1)

# {set1:'v'} # TypeError: unhashable type: 'set'
set1.pop()
print(set1)
set1.remove(1.1)
print(set1)
# update()：传入一个新的set 将两个set中的所有元素进行去重 得到最后的结果
set1.update({1, 2, 3, 4, 5, 6, 7})
print(set1)